package lib.rv.ap

import android.annotation.SuppressLint
import android.view.LayoutInflater
import lib.rv.BR
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView

/**
 * VH： 对应 ViewHolder
 *
 */
abstract class BaseRvAdapter<M : IViewTypeModel> :
    RecyclerView.Adapter<BaseRvAdapter.BindingViewHolder>() {
    // 数据源
    private val items: MutableList<M> = ArrayList()

    // 针对每一种ViewType的业务处理
    private val mVtdManager = ViewTypeDelegateManager<M>()
    private var mInflater: LayoutInflater? = null
    private var itemIds: ItemIds<in M>? = null

    abstract fun onCreateVHForAll(b: ViewDataBinding)

    abstract fun onBindVHForAll(b: ViewDataBinding, m: M)

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        addViewTypeDelegate(mVtdManager)
        super.onAttachedToRecyclerView(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        mVtdManager.clear()
        super.onDetachedFromRecyclerView(recyclerView)
    }

    override fun getItemCount(): Int {
        return items.size
    }

    @LayoutRes
    override fun getItemViewType(position: Int): Int {
        return items[position].getViewType()
    }

    override fun onCreateViewHolder(parent: ViewGroup, @LayoutRes viewType: Int): BindingViewHolder {
        val holder = createVH(parent, viewType)
        onCreateVHForAll(holder.b)
        mVtdManager.onCreateVH(holder.b, viewType)
        return holder
    }

    override fun onBindViewHolder(holder: BindingViewHolder, position: Int) {
        val item = items[position]
        onBindVHForAll(holder.b, item)
        mVtdManager.onBindVH(holder.b, item)
        holder.b.executePendingBindings()
    }

    /**
     * 初始化各种 viewType 处理委托。添加到 Manager 中。
     */
    protected open fun addViewTypeDelegate(manager: ViewTypeDelegateManager<M>) {

    }

    /**
     * 获取数据。
     */
    fun getItems(): MutableList<M> {
        return items
    }

    /**
     * 设置数据
     */
    @SuppressLint("NotifyDataSetChanged")
    fun setItems(list: List<M>) {
        items.clear()
        items.addAll(list)
        notifyDataSetChanged()
    }

    /**
     * 添加数据
     */
    fun addItems(list: List<M>) {
        val preSize = items.size
        items.addAll(list)
        notifyItemRangeInserted(preSize, list.size)
    }

    /**
     * 只刷新局部数据。
     */
    fun changeItem(list: List<M>) {
        for (m in list) {
            val index = items.indexOf(m)
            if (index >= 0) {
                notifyItemChanged(index)
            }
        }
    }

    /**
     * 只移除局部数据。
     */
    fun removeItem(list: List<M>) {
        for (m in list) {
            if (m in items) {
                val index = items.indexOf(m)
                items.remove(m)
                notifyItemRemoved(index)
            }
        }
    }

    /**
     * 只移除局部数据。
     */
    fun removeItem(vararg ms: M) {
        removeItem(ms.toList())
    }
    /**
     * 设置数据
     */
//    fun setItems(vararg ms: M) {
//        setItems(ms.toList())
//    }


    /**
     * 清空数据
     */
    fun clearData() {
        items.clear()
    }

    protected open fun createVH(parent: ViewGroup, @LayoutRes viewType: Int): BindingViewHolder {
        if (mInflater == null) {
            mInflater = LayoutInflater.from(parent.context)
        }
        val b = DataBindingUtil.inflate<ViewDataBinding>(
            mInflater!!, viewType, parent, false
        )
        return BindingViewHolder(b)
    }

    /**
     * List数据结构需要改变时重写。即传入 List 经过变化后变成 items 需要的list。默认不改变结构。
     */
//    @Suppress("UselessCallOnCollection")
//    protected open fun multiList(list: List<M>): List<M> {
//        return list.filterNotNull()
//    }
    /**
     * IllegalStateException -> Cannot change whether this adapter has stable IDs while the adapter has registered observers
     * Set the item id's for the items. If not null, this will set [ ][RecyclerView.Adapter.setHasStableIds] to true.
     */
    fun setItemIds(ids: ItemIds<in M>?) {
        if (itemIds == null && itemIds != ids) {
            this.itemIds = ids
            setHasStableIds(true)
        }
    }

    /**
     * 此方法只在setHasStableIds设置为true才会生效
     * 1、如果只返回position,当item位置改变,数据会错乱
     * 2、不重写的话,当前grid_span=2的布局时,item刷新会闪烁,因为item在重新测量,要么写死item的宽高解决问题
     * 3、要么返回具体的itemId.如果返回position, 列表滑动到下面,此时刷新还是会闪烁
     */
    override fun getItemId(position: Int): Long {
        if (itemIds == null) {
            return position.toLong()
        }
        return itemIds!!.getItemId(position, items[position])
    }

    class BindingViewHolder(val b: ViewDataBinding) : RecyclerView.ViewHolder(b.root)

    interface ItemIds<T> {
        fun getItemId(position: Int, item: T): Long
    }
}